#include <iostream>
#include "trace.h"
#include "general.h"
#include "constants.h"
#include <deque>
#include <vector>
#include <ctime>
#include <string>
#include <algorithm>

using namespace std;

struct T2F_node
{
	Position pos;
	int globalID;
	int domainID;
	
	int totalBuffer;
	int totalSend;
	int totalReceive;
	int totalCollision;
	deque<Traffic> nodeTraffic;

	bool isSender;
	int sendTo;
	int receiveFrom;

	int state;
	int countingDown;
	int waitCount;

	int contendSubcarrier;
	int rank;
};

struct T2F
{
/*
	SIFS-SFC-DATA-(SIFS-RFC-DATA)-ACK
*/
	T2F_node t2f_nodes[2][MAX_NODE];		// keep two copys
	vector<int> t2f_neighborList[MAX_NODE];	// keep the neighbors
	Trace trace;
	int nodeNum;
	ofstream msgout;
	int t_data;				// time needed for data transmission
	int K;					// number of nodes to round2

	int receiveCount;
	int sendCount;
	int collisionCount;
	int time;

	//int datarate;			// in (Mbps)

	void initial(Trace trace, int datarate = 6, int setK = 3)
	{
		this->trace = trace;
		this->nodeNum = trace.nodeNum;
		memset(t2f_nodes, 0, sizeof(T2F_node));

		this->t_data = 1500 * 8 / datarate;
		this->K = setK;

		// initial nodes' location, id, etc.
		for (int i = 0; i < trace.nodeNum; i++)
		{
			for (int j = 0; j < 2; j++)
			{
				t2f_nodes[j][i].globalID = i;
				t2f_nodes[j][i].domainID = trace.nodes_id[i];
				t2f_nodes[j][i].pos = trace.nodes_position[i];
				t2f_nodes[j][i].isSender = false;
				t2f_nodes[j][i].totalBuffer = 0;
				t2f_nodes[j][i].totalReceive = 0;
				t2f_nodes[j][i].totalSend = 0;
				t2f_nodes[j][i].totalCollision = 0;
				t2f_nodes[j][i].nodeTraffic.clear();
				t2f_nodes[j][i].state = STATE_IDLE;
				t2f_nodes[j][i].contendSubcarrier = 0;
				t2f_nodes[j][i].rank =  -1;
				t2f_nodes[j][i].countingDown = 0;
				t2f_nodes[j][i].waitCount = 0;
			}
		}

		// initial nodes' neighbors
		for (int i = 0; i < nodeNum; i++)
		{
			for (int j = 0; j < nodeNum; j++)
			{
				if (i != j && t2f_nodes[0][i].pos.isNeighbor(t2f_nodes[0][j].pos))
				{
					t2f_neighborList[i].push_back(j);
				}
			}
		}
		msgout.open("t2f_debug.txt");
	}

	// run the t2f_mac, for runtime (in millisecond)
	void start_mac(int runtime = 0)
	{
		int seed = (unsigned int)std::time(NULL);
		srand(seed);
		msgout << seed << endl;

		time = 0;
		while (time < 200 * 1000/* || runtime == 0*/)		// runtime == 0: wait until all over
		{
			time++;

			// check traffic trace for all the nodes
			if (!trace.nodes_traffic.empty())
			{
				while (trace.nodes_traffic[0].time_slot <= time)
				{
					int sender = trace.nodes_traffic[0].sender_id;
					int pkt = trace.nodes_traffic[0].pkt_number;
					for (int i = 0; i < 2; i++)
					{
						t2f_nodes[i][sender].totalBuffer += pkt;
						t2f_nodes[i][sender].nodeTraffic.push_back(trace.nodes_traffic[0]);
					}
					trace.nodes_traffic.pop_front();
					if (trace.nodes_traffic.empty())
						break;
				}
			}
			else	// actually no work to do
			{
				int shouldExit = true;
				for (int id = 0; id < nodeNum; id++)
					if (t2f_nodes[0][id].totalBuffer != 0)
					{
						shouldExit = false;
						break;
					}
				if (shouldExit)
					break;
			}

			for (int id = 0; id < nodeNum; id++)
			{
				switch (this->t2f_nodes[0][id].state)
				{
				case STATE_IDLE:
					process_idle(id, time);
					break;
				case STATE_DIFS:
					process_difs(id, time);
					break;
				case STATE_ROUND1:
					process_round1(id, time);
					break;
				case STATE_ROUND2:
					process_round2(id, time);
					break;
				case STATE_WAIT:
					process_wait(id, time);
					break;
				case STATE_PIFS:
					process_pifs(id, time);
					break;
				case STATE_SDATA:
					process_sdata(id, time);
					break;
				case STATE_RDATA:
					process_rdata(id, time);
					break;
				case STATE_WRDATA:
					process_wrdata(id, time);
					break;
				case STATE_PRDATA:
					process_prdata(id, time);
					break;
				case STATE_SACK :
					process_sack(id, time);
					break;
				case STATE_RACK:
					process_rack(id, time);
					break;
				case STATE_WRACK:
					process_wrack(id, time);
					break;
				case STATE_PRACK:
					process_prack(id, time);
					break;
				}
			}
			copyState();							// copy the state of [1] to [0];
		}

		this->receiveCount = 0;
		this->sendCount = 0;
		this->collisionCount = 0;
		for (int i = 0; i < nodeNum; i++)
		{
			receiveCount += this->t2f_nodes[0][i].totalReceive;
			sendCount += this->t2f_nodes[0][i].totalSend;
			collisionCount += this->t2f_nodes[0][i].totalCollision;
		}
		
		msgout << receiveCount << " " << sendCount << " " << collisionCount << endl;
		cout << receiveCount << " " << sendCount << " " << collisionCount << endl;

		msgout.close();
	}

	void copyNode(const T2F_node& from, T2F_node &to)
	{
		//Position pos;
		//int globalID;
		//int domainID;
	
		to.totalBuffer = from.totalBuffer;
		to.totalSend = from.totalSend;
		to.totalReceive = from.totalReceive;
		to.totalCollision = from.totalCollision;

		to.nodeTraffic.clear();
		for (deque<Traffic>::const_iterator it = from.nodeTraffic.begin(); it != from.nodeTraffic.end(); it++)
		{
			to.nodeTraffic.push_back(*it);
		}

		to.isSender = from.isSender;
		to.sendTo = from.sendTo;
		to.receiveFrom = from.receiveFrom;;

		to.state = from.state;
		to.countingDown = from.countingDown;

		to.contendSubcarrier = from.contendSubcarrier;
		to.waitCount = from.waitCount;
		to.rank = from.rank;
	}

	void copyState()
	{
		for (int i = 0; i < nodeNum; i++)		
		{
			copyNode(t2f_nodes[1][i], t2f_nodes[0][i]);
		}
	}

	void process_rack(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];

		if (node_new.countingDown > 0)
			node_new.countingDown--;
		else
		{
			// done, back to IDLE
			updateStateMsg(time, node_new, "RACK-->IDLE");
			node_new.state = STATE_IDLE;
			node_new.isSender = false;
			node_new.receiveFrom = -1;
			node_new.sendTo = -1;
			node_new.countingDown = 0;
			node_new.rank = -1;
			node_new.contendSubcarrier = -1;
			return;	
		}
	}

	void process_rdata(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];

		if (node_new.countingDown > 0)
		{
			if (checkCollision(id, node_new.receiveFrom))	// collision, back to idle
			{
				updateStateMsg(time, node_new, "RDATA-->IDLE");
				node_new.state = STATE_IDLE;
				node_new.isSender = false;
				node_new.receiveFrom = -1;
				node_new.sendTo = -1;
				node_new.countingDown = 0;
				node_new.rank = -1;
				node_new.contendSubcarrier = -1;
				return;				
			}
			else
				node_new.countingDown--;
		}
		else
		{
			node_new.totalReceive++;		// received one more packet

			updateStateMsg(time, node_new, "RDATA-->RACK");
			node_new.state = STATE_RACK;
			node_new.countingDown = T_SIFS + T_ACK;
			node_new.rank = -1;
			node_new.contendSubcarrier = -1;
			return;			
		}
	}

	// used only for pifs-->rdata-->rack
	void process_prack(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];

		if (node_new.countingDown > 0)
			node_new.countingDown--;
		else
		{
			// done, back to wait
			updateStateMsg(time, node_new, "PRACK-->PIFS");
			node_new.state = STATE_PIFS;
			node_new.isSender = false;
			node_new.receiveFrom = -1;
			node_new.sendTo = -1;
			node_new.countingDown = T_PIFS;
			node_new.waitCount = 0;
			return;	
		}
	}

	// used only for wait-->rdata
	void process_prdata(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];

		if (node_new.countingDown > 0)
		{
			if (checkCollision(id, node_new.receiveFrom))	// collision, back to idle
			{
				updateStateMsg(time, node_new, "PRDATA-->PIFS");
				node_new.state = STATE_PIFS;
				node_new.isSender = false;
				node_new.receiveFrom = -1;
				node_new.sendTo = -1;
				node_new.countingDown = T_PIFS;
				node_new.waitCount = 0;
				return;				
			}
			else
				node_new.countingDown--;
		}
		else
		{
			node_new.totalReceive++;		// received one more packet

			updateStateMsg(time, node_new, "PRDATA-->PRACK");
			node_new.state = STATE_PRACK;
			node_new.countingDown = T_SIFS + T_ACK;
			return;			
		}
	}

	void process_pifs(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];

		node_new.waitCount++;
		// wait too long, abort this transmission
		if (node_new.waitCount > (this->K + 100) * this->t_data)
		{
			updateStateMsg(time, node_new, "PIFS-->IDLE");
			node_new.state = STATE_IDLE;
			node_new.countingDown = 0;
			node_new.waitCount = 0;
			node_new.isSender = false;
			node_new.sendTo = -1;
			node_new.receiveFrom = -1;
			node_new.rank = -1;
			node_new.contendSubcarrier = -1;
			return;
		}

		if (node_new.countingDown > 0)
		{
			// check whether is a receiver
			int senderID = -1;
			if (checkReceiver(node_new.globalID, senderID))		// someone in SDATA, and the receiver is this node
			{
				updateStateMsg(time, node_new, "PIFS-->PRDATA");
				node_new.state = STATE_PRDATA;
				node_new.receiveFrom = senderID;
				node_new.isSender = false;
				node_new.countingDown = this->t2f_nodes[0][senderID].countingDown - 1;
				node_new.waitCount = 0;
				return;
			}

			if (checkCollision(id, id))
				node_new.countingDown = T_PIFS;
			else
				node_new.countingDown--;
		}
		else // end of PIFS, go to SDATA
		{
			updateStateMsg(time, node_new, "PIFS-->SDATA");
			node_new.state = STATE_SDATA;
			node_new.countingDown = this->t_data;
			node_new.isSender = true;
			node_new.sendTo = node_new.nodeTraffic[0].receiver_id;
			node_new.receiveFrom = -1;
			node_new.waitCount = 0;
		}
	}

	// used only for wait-->rdata-->rack
	void process_wrack(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];

		if (node_new.countingDown > 0)
			node_new.countingDown--;
		else
		{
			// done, back to wait
			updateStateMsg(time, node_new, "WRACK-->WAIT");
			node_new.state = STATE_WAIT;
			node_new.isSender = false;
			node_new.receiveFrom = -1;
			node_new.sendTo = -1;
			node_new.countingDown = 0;
			node_new.waitCount = 0;
		}
	}

	// used only for wait-->rdata
	void process_wrdata(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];

		if (node_new.countingDown > 0)
		{
			if (checkCollision(id, node_new.receiveFrom))	// collision, back to idle
			{
				updateStateMsg(time, node_new, "WRDATA-->WAIT");
				node_new.state = STATE_WAIT;
				node_new.isSender = false;
				node_new.receiveFrom = -1;
				node_new.sendTo = -1;
				node_new.countingDown = 0;
				node_new.waitCount = 0;
				return;				
			}
			else
				node_new.countingDown--;
		}
		else
		{
			node_new.totalReceive++;		// received one more packet

			updateStateMsg(time, node_new, "WRDATA-->WRACK");
			node_new.state = STATE_WRACK;
			node_new.countingDown = T_SIFS + T_ACK;
			return;			
		}
	}

	void process_wait(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];
		
		node_new.waitCount++;
		// wait too long, abort this transmission
		if (node_new.waitCount > (this->K + 100) * this->t_data)
		{
			updateStateMsg(time, node_new, "WAIT-->IDLE");
			node_new.state = STATE_IDLE;
			node_new.countingDown = 0;
			node_new.waitCount = 0;
			node_new.isSender = false;
			node_new.sendTo = -1;
			node_new.receiveFrom = -1;
			node_new.rank = -1;
			node_new.contendSubcarrier = -1;
			return;
		}

		// not a receiver, whether its precursor is now transmission
		for (vector<int>::iterator it = this->t2f_neighborList[id].begin(); it != this->t2f_neighborList[id].end(); it++)
		{
			T2F_node neighbor = t2f_nodes[0][*it];

			// some neighbor has perform contension
			if (neighbor.isSender && neighbor.state == STATE_SDATA && neighbor.rank == node_new.rank - 1)
			{
				if (!checkCollision(id, neighbor.globalID))		// heard part of the pkt, go to PIFS
				{
					updateStateMsg(time, node_new, "WAIT->PIFS");
					node_new.state = STATE_PIFS;
					node_new.countingDown = T_PIFS;
					node_new.waitCount = 0;
					return;
				}
			}
		}

		// check whether is a receiver
		int senderID = -1;
		if (checkReceiver(node_new.globalID, senderID))		// someone in SDATA, and the receiver is this node
		{
			updateStateMsg(time, node_new, "WAIT-->WRDATA");
			node_new.state = STATE_WRDATA;
			node_new.receiveFrom = senderID;
			node_new.isSender = false;
			node_new.countingDown = this->t2f_nodes[0][senderID].countingDown - 1;
			node_new.waitCount = 0;
			return;
		}

		// otherwier, keep waiting
	}

	void process_sack(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];

		if (node_new.countingDown > 0)
		{
			if (node_new.countingDown < T_ACK && checkCollision(id, node_new.sendTo))	// ack is collided, resend
			{
				updateStateMsg(time, node_new, "SACK-->IDLE");
				node_new.state = STATE_IDLE;
				node_new.countingDown = 0;
				node_new.isSender = false;
				node_new.sendTo = -1;
				node_new.receiveFrom = -1;
				node_new.rank = -1;
				node_new.contendSubcarrier = -1;				
			}
			else
				node_new.countingDown--;
		}
		else	// no collision
		{
			if (
				(this->t2f_nodes[0][node_new.sendTo].state == STATE_RACK				// check whether there is an ack
				|| this->t2f_nodes[0][node_new.sendTo].state == STATE_WRACK 
				|| this->t2f_nodes[0][node_new.sendTo].state == STATE_PRACK) 
				&& (this->t2f_nodes[0][node_new.sendTo].receiveFrom == node_new.globalID)
				)
			{
				node_new.totalSend++;
				node_new.nodeTraffic[0].pkt_number--;
				node_new.totalBuffer--;
				finishPktMsg(time, node_new.globalID, node_new.sendTo);
				if (node_new.nodeTraffic[0].pkt_number == 0)	// whether anything more
				{
					node_new.nodeTraffic.pop_front();
					updateStateMsg(time, node_new, "SACK-->IDLE");
					node_new.state = STATE_IDLE;
					node_new.countingDown = 0;
					node_new.isSender = false;
					node_new.sendTo = -1;
					node_new.receiveFrom = -1;
					node_new.rank = -1;
					node_new.contendSubcarrier = -1;
				}
				else		// more pkt to send, to DIFS
				{
					updateStateMsg(time, node_new, "SACK-->DIFS");
					node_new.state = STATE_DIFS;
					node_new.countingDown = T_DIFS;
					node_new.isSender = false;
					node_new.sendTo = -1;
					node_new.receiveFrom = -1;
					node_new.rank = -1;
					node_new.contendSubcarrier = -1;
				}
			}
			else	// no ack, back to DIFS
			{
				node_new.totalCollision++;
				updateStateMsg(time, node_new, "SACK-->DIFS");
				node_new.state = STATE_DIFS;
				node_new.countingDown = T_DIFS;
				node_new.isSender = false;
				node_new.sendTo = -1;
				node_new.receiveFrom = -1;
				node_new.rank = -1;
				node_new.contendSubcarrier = -1;
				return;
			}
		}
	}

	void process_sdata(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];

		if (node_new.countingDown > 0)
		{
			node_new.countingDown--;
		}
		else
		{
			updateStateMsg(time, node_new, "SFC-->SACK");
			node_new.state = STATE_SACK;
			node_new.countingDown = T_SIFS + T_ACK;
			//node_new.rank = -1;					// need to keep the rank information to let other nodes know it's over
			//node_new.contendSubcarrier = -1;
			return;				
		}
	}	

	void process_round2(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];

		if (node_new.countingDown > 0)
		{
			node_new.countingDown--;
		}
		else	// end of sfc, check if it wins
		{
			int rank = checkRound2Rank(id);
			if (rank == 0)			// be the first in round2, directly go to SDATA
			{
				// win, be a sender and move to sdata
				updateStateMsg(time, node_new, "ROUND1-->SDATA");
				node_new.state = STATE_SDATA;
				node_new.countingDown = this->t_data;
				node_new.isSender = true;
				node_new.sendTo = node_new.nodeTraffic[0].receiver_id;
				node_new.rank = rank;
				node_new.receiveFrom = -1;
				return;	
			}
			else	// go to wait, wait for lower rank to be finished
			{
				updateStateMsg(time, node_new, "ROUND2-->WAIT");
				node_new.state = STATE_WAIT;
				node_new.countingDown = 0;
				node_new.waitCount = 0;
				node_new.isSender = false;
				node_new.sendTo = -1;
				node_new.receiveFrom = -1;
				node_new.rank = rank;
				return;	
			}
		}
	}

	void process_round1(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];

		if (node_new.countingDown > 0)
		{
			node_new.countingDown--;
		}
		else	// end of sfc, check if it wins
		{
			if (checkRound1Win(id))			// win in round1, move to round2
			{
				// win, be a sender and move to sdata
				updateStateMsg(time, node_new, "ROUND1-->ROUND2");
				node_new.state = STATE_ROUND2;
				node_new.countingDown = T_SFC;
				node_new.receiveFrom = -1;
				node_new.rank = -1;
				node_new.contendSubcarrier = rand() % NUM_SUBCARRIER + 1;
				return;	
			}
			else	// lose, go back to DIFS
			{
				updateStateMsg(time, node_new, "ROUND1-->DIFS");
				node_new.state = STATE_DIFS;
				node_new.countingDown = T_DIFS;
				node_new.isSender = false;
				node_new.sendTo = -1;
				node_new.receiveFrom = -1;
				node_new.rank = -1;
				node_new.contendSubcarrier = -1;
				return;	
			}
		}
	}

	void process_difs(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];

		if (node_new.countingDown > 0)
		{
			if (checkCollision(id, id))
			{
				int senderID = -1;
				if (checkReceiver(node_new.globalID, senderID))		// someone in SDATA, and the receiver is this node
				{
					updateStateMsg(time, node_new, "DIFS-->RDATA");
					node_new.state = STATE_RDATA;
					node_new.receiveFrom = senderID;
					node_new.isSender = false;
					node_new.sendTo = -1;
					node_new.countingDown = this->t2f_nodes[0][senderID].countingDown - 1;
					node_new.rank = -1;
					node_new.contendSubcarrier = -1;
					return;
				}
				else
					node_new.countingDown = T_DIFS;
			}
			else
				node_new.countingDown--;
		}
		else // end of DIFS, go to SFC
		{
			// the case for the first packet, the sender should contend for itself
			updateStateMsg(time, node_new, "DIFS-->ROUND1");
			node_new.state = STATE_ROUND1;
			node_new.contendSubcarrier = rand() % NUM_SUBCARRIER + 1;
			node_new.rank = -1;
			node_new.countingDown = T_SFC;
			return;
		}
	}

	void process_idle(int id, int time)
	{
		T2F_node &node_old = t2f_nodes[0][id];
		T2F_node &node_new = t2f_nodes[1][id];
		if (node_old.totalBuffer != 0)
		{
			updateStateMsg(time, node_new, "IDLE-->DIFS");
			node_new.state = STATE_DIFS;
			node_new.countingDown = T_DIFS;
			node_new.contendSubcarrier = -1;
			node_new.rank = -1;
		}
		else 
		{
			int senderID = -1;
			if (checkReceiver(node_new.globalID, senderID))		// someone in SDATA, and the receiver is this node
			{
				updateStateMsg(time, node_new, "IDLE-->RDATA");
				node_new.state = STATE_RDATA;
				node_new.receiveFrom = senderID;
				node_new.isSender = false;
				node_new.sendTo = -1;
				node_new.countingDown = this->t2f_nodes[0][senderID].countingDown - 1;
			}
		}
	}

	// get all active subcarriers around nodeID
	void getAllSubcarrier(vector<int> &ranks, int nodeID, int state)
	{
		ranks.clear();
		ranks.push_back(t2f_nodes[0][nodeID].contendSubcarrier);

		for (vector<int>::iterator it = this->t2f_neighborList[nodeID].begin(); it != this->t2f_neighborList[nodeID].end(); it++)
		{
			T2F_node neighbor = t2f_nodes[0][*it];

			if (neighbor.contendSubcarrier > 0 /*&& neighbor.state == state*/)
			{
				bool isExisted = false;
				for (vector<int>::iterator jt = ranks.begin(); jt != ranks.end(); jt++)
					if (neighbor.contendSubcarrier == *jt)
					{
						isExisted = true;
						break;
					}
				if (!isExisted)
					ranks.push_back(neighbor.contendSubcarrier);
			}
		}

		// sort the subcarriers
		sort(ranks.begin(), ranks.end());
	}

	// whether the node wins in the contension
	int checkRound2Rank(int nodeID)
	{
		T2F_node node = this->t2f_nodes[0][nodeID];

		vector<int> ranks;
		ranks.clear();

		getAllSubcarrier(ranks, nodeID, STATE_ROUND2);
		for (int i = 0; i < (int)ranks.size(); i++)
			if (node.contendSubcarrier == ranks[i])
				return i;

		// something wrong
		return -1;
	}

	// whether the node wins in the contension
	bool checkRound1Win(int nodeID)
	{
		T2F_node node = this->t2f_nodes[0][nodeID];

		vector<int> ranks;
		ranks.clear();

		getAllSubcarrier(ranks, nodeID, STATE_ROUND2);
		for (int i = 0; i < min(K, (int)ranks.size()); i++)
			if (node.contendSubcarrier == ranks[i])
				return true;
		return false;
	}

	// whether some neighbor wants to send someting to node and this node wins in the contension
	bool checkReceiver(int receiverID, int& senderID)
	{
		T2F_node receiver = this->t2f_nodes[0][receiverID];
		senderID = -1;
		for (vector<int>::iterator it = this->t2f_neighborList[receiverID].begin(); it != this->t2f_neighborList[receiverID].end(); it++)
		{
			T2F_node neighbor = t2f_nodes[0][*it];

			// some neighbor has perform contension
			if (neighbor.isSender && neighbor.state == STATE_SDATA && neighbor.sendTo == receiverID  && neighbor.countingDown >= this->t_data - 10)
			{
				senderID = neighbor.globalID;
			}
		}

		// no one is in SFC
		if (senderID < 0)
			return false;
		else if (checkCollision(receiverID, senderID))
			return false;
		else
			return true;
	}

	// whether the link sender-->receiver is failed due to collision
	bool checkCollision(int receiverID, int senderID)
	{
		T2F_node receiver = this->t2f_nodes[0][receiverID];
		T2F_node sender = this->t2f_nodes[0][senderID];
		for (vector<int>::iterator it = this->t2f_neighborList[receiverID].begin(); it != this->t2f_neighborList[receiverID].end(); it++)
		{
			T2F_node neighbor = t2f_nodes[0][*it];
			if (neighbor.globalID == sender.globalID)
				continue;

			// someone else is also a sender
			if (neighbor.state == STATE_SDATA || neighbor.state == STATE_ROUND1
				|| neighbor.state == STATE_ROUND2 
				|| ((neighbor.state == STATE_RACK || neighbor.state == STATE_WRACK || neighbor.state == STATE_PRACK) && neighbor.countingDown < T_ACK)
				)
			{
				return true;
			}
		}
		return false;
	}

	void updateStateMsg(int time, const T2F_node& node, string msg)
	{
		// Use this to print something
		//string not = "";
		//if (!node.isSender)
		//	not += " NOT";
		//cout << time << " node " << node.globalID << "(" << node.domainID << ") is" << not << " sender: " << msg << endl;
		//msgout << time << " node " << node.globalID << "(" << node.domainID << ") is" << not << " sender: " << msg << endl;
	}

	void finishPktMsg(int time, int from, int to)
	{
		cout << time << " FINISH: " << from << "-->" << to << endl;
		msgout << time << " FINISH: " << from << "-->" << to << endl;
	}
};